from PyQt6.QtWidgets import (QWidget, QMenu, QPushButton, QLabel, QLineEdit)
from PyQt6.QtGui import QAction

import pyqtgraph as pg
from pyqtgraph.Qt import QtCore

def load_and_clone_widgets_from_ui(file_path: str):
    """
    复制控件信息。
    :param ui_file_path: ui文件路径。
    :return: _description_
    """
    from PyQt6.uic.load_ui import loadUi
    # 1. 动态加载 UI 文件到一个临时窗口（不显示）
    temp_window = loadUi(file_path)  # 加载UI，控件成为temp_window的子控件
    # 2. 遍历所有子控件
    widgets = temp_window.findChildren(QWidget)
    cloned_widgets_info = []

    for widget in widgets:
        # 跳过布局等非交互控件（可选）
        if not widget.objectName():  # 如果没有设置objectName，可以选择跳过
            continue
        # 获取控件属性
        class_name = widget.metaObject().className()  # 如 "QPushButton"
        obj_name = widget.objectName()
        geo = widget.geometry()  # QRect(x, y, w, h)
        style = widget.styleSheet()
        if class_name != 'QGroupBox':
            text = getattr(widget, 'text', lambda: '')() # 如按钮文字、标签文本
        else:
            text = getattr(widget, 'title', lambda: '')()
        placeholder = ""
        if isinstance(widget, QLineEdit):
            placeholder = widget.placeholderText()
        print(f"\n发现控件: {class_name} | objectName={obj_name} | pos={geo.x()}, {geo.y()} | size={geo.width()}x{geo.height()}")
        print(f"  text={text}, style={style}")
        # 保存信息，用于后续克隆
        cloned_widgets_info.append({
            "class_name": class_name,
            "object_name": obj_name,
            "geometry": geo,
            "style_sheet": style,
            "text": text,
            "placeholder": placeholder
        })
    # 3. 销毁临时窗口
    temp_window.deleteLater()
    return cloned_widgets_info

def create_cloned_widget(info: dict):
    """
    创建复制的控件。根据类名动态创建控件。
    :param info: 控件信息。
    :return: _description_
    """
    from PyQt6.QtWidgets import QGroupBox
    class_map = {
        "QPushButton": QPushButton,
        "QLabel": QLabel,
        "QLineEdit": QLineEdit,
        "QGroupBox": QGroupBox

    }  # 可继续添加其它控件类型，如 QComboBox, QCheckBox 等
    cls = class_map.get(info["class_name"])
    if not cls:
        print(f"⚠️ 不支持的控件类型: {info['class_name']}")
        return None
    # 创建新控件（无父！非常重要！）
    widget: QWidget = cls()
    # 设置基本属性
    widget.setObjectName(info["object_name"])
    widget.setFixedSize(info["geometry"].width(), info['geometry'].height())  # 设置位置和大小
    if info["style_sheet"]:
        widget.setStyleSheet(info["style_sheet"])  # 设置样式表
    if hasattr(widget, 'setText') and info["text"]:
        widget.setText(info["text"])  # 如按钮、标签的文字
    if hasattr(widget, 'setTitle') and info["text"]:
        widget.setTitle(info["text"])  # 如按钮、标签的文字
    if hasattr(widget, 'setPlaceholderText') and info["placeholder"]:
        widget.setPlaceholderText(info["placeholder"])  # QLineEdit 占位符
    return widget


class CustomGraphicsView(pg.GraphicsView):
    """
    继承pg.GraphicsView，添加了viewBox。
    1，添加控件，可设置宽高、位置和鼠标事件。
    """
    class ContextMenu:
        """
        自定义右键菜单。
        """
        def __init__(self):
            self.menu = QMenu()

        def add_action(self, text: str, callback):
            """
            为菜单添加动作。
            :param text: 菜单选项文本。
            :param callback: 回调函数。
            :return: 返回动作对象。
            """
            action = QAction(text, self.menu)
            action.triggered.connect(callback)
            self.menu.addAction(action)
            return action

        def add_submenu(self, text: str):
            """
            添加子菜单。
            :param text: 菜单选项文本。
            :return: 返回子菜单对象，方便后续添加子项
            """
            submenu = QMenu(text, self.menu)
            self.menu.addMenu(submenu)
            return submenu  

        def get_menu(self):
            """
            返回菜单对象。
            :return: 菜单对象。
            """
            return self.menu

    def __init__(self, parent=None, useOpenGL=None, background='default'):
        super().__init__(parent, useOpenGL, background)
        # 初始化UI和ViewBox
        self.viewBox = pg.ViewBox(invertY=True, lockAspect=False)
        self.setCentralItem(self.viewBox)
        self.context_menu = CustomGraphicsView.ContextMenu()  # 初始化自定义菜单
        pg.setConfigOptions(antialias=True)

    def contextMenuEvent(self, event):
        """
        重写菜单事件函数，确保菜单在正确的位置显示。
        :param event: QContextEvent
        """
        self.context_menu.get_menu().exec(event.globalPos())  # 在鼠标位置生成菜单并等待

    def add_widget_to_viewbox(self, widget: QWidget, x, y, **kwargs):
        """
        将控件添加到ViewBox中，基于ImageItem的像素坐标系指定位置和大小。
        :param widget: PyQt控件（如QPushButton, QLineEdit）
        """
        from PyQt6.QtWidgets import QGraphicsProxyWidget
        # 确保widget没有父控件！
        if widget.parent() is not None:
            print(f"⚠️ 控件 {widget.objectName()} 有父控件，无法嵌入！请确保它是独立的。")
            return
        # 创建代理
        proxy = QGraphicsProxyWidget()
        proxy.setWidget(widget)  # ✅ 只有独立的 widget 才能嵌入
        # 可选：设置代理的位置（如果 widget 的 geometry 已经包含位置，可以不用再设置 proxy 的 pos）
        proxy.setPos(x, y)
        key = 'mousePressEvent'
        if key in kwargs:
            proxy.mousePressEvent = kwargs[key]
        self.viewBox.addItem(proxy)
        return proxy

if __name__ == '__main__':
    import sys
    from PyQt6.QtWidgets import QPushButton, QApplication
    from pyqtgraph import QtWidgets
    from pyqtgraph.Qt import QtCore

    app = QApplication(sys.argv)
    win = QtWidgets.QMainWindow()
    win.resize(800,800)
    window = CustomGraphicsView()

    b = QPushButton()
    b.setFixedSize(50, 30)

    def fun(event):
        if event.button() == QtCore.Qt.MouseButton.LeftButton:
            print('l')
        if event.button() == QtCore.Qt.MouseButton.RightButton:
            print('r')

    window.add_widget_to_viewbox(b, 100, 200, mousePressEvent=fun)
    win.setCentralWidget(window)
    win.show()
    sys.exit(app.exec())
